﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Jayden.Dll.Core;
using Jayden.Dll.Cards.Poker;
using Jayden.Dll.Core.Persistence;
using System.Net;
using Jayden.Dll.Web.Json;
using System.Globalization;

namespace Jayden.Windows.PokerWatcher
{
	static class Program
	{
		public static TexasHoldemHandRangeModel SklanskyLevels;
		public static TexasHoldemHandRangeModel PhilHellmutLevels;

		public static double USDRatio = 0.77;

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			bool updateRatio = false;
			bool computeSegmentation = false;
			bool testing = false;

			if (updateRatio || computeSegmentation)
			{
				try
				{
					WebClient client = new WebClient();
					string jsonResponse = client.DownloadString("http://www.google.com/ig/calculator?hl=en&q=1USD=?EUR");
					JsonObject response = JsonHelper.ParseJson(jsonResponse) as JsonObject;
					string valueString = (response["rhs"] as JsonString).Value;
					string[] valueArray = valueString.Split(' ');
					double usdRatio = double.Parse(valueArray[0], CultureInfo.InvariantCulture);
					USDRatio = usdRatio;
				}
				catch
				{
					USDRatio = 0.77;
				}
			}

			// http://en.wikipedia.org/wiki/Texas_hold_'em_starting_hands

			PhilHellmutLevels = new TexasHoldemHandRangeModel();
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("AA, KK, AKs, QQ, AKo"));
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("JJ, TT, 99"));
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("88, 77, AQs, AQo"));
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("AJs, ATs, A9s, A8s"));
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("A7s, A6s, A5s, A4s, A3s, A2s, KQs, KQo"));
			PhilHellmutLevels.Add(TexasHoldemHandRangeList.Parse("QJs, JTs, T9s, 98s, 87s, 76s, 65s"));

			SklanskyLevels = new TexasHoldemHandRangeModel();
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("JJ+, AKs"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("TT, AQs, AJs, KQs, AKo"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("99, ATs, KJs, QJs, JTs, AQo"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("88, KTs, QTs, J9s, T9s, 98s, AJo, KQo"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("77, A2s-A9s, Q9s, T8s, 97s, 87s, 76s, KJo, QJo, JTo"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("66, 55, K9s, J8s, 86s, 75s, 54s, ATo, KTo, QTo"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("22-44, K2s-K8s, Q8s, T7s, 64s, 53s, 43s, J9o, T9o, 98o"));
			SklanskyLevels.Add(TexasHoldemHandRangeList.Parse("J7s, 96s, 85s, 74s, 42s, 32s, A9o, K9o, Q9o, J8o, T8o, 87o, 76o, 65o, 54o"));

			Application.EnableVisualStyles();
			Application.SetCompatibleTextRenderingDefault(false);

			Configuration configuration = new Configuration("Configuration.xml");
			UnitOfWork uow = new UnitOfWork(configuration.GetConfiguration("UnitOfWork"));

			if (testing)
			{

				PokerWatcherForm pokerWatcherForm = new PokerWatcherForm();
				pokerWatcherForm.Configuration = configuration;
				pokerWatcherForm.UnitOfWork = uow;

				TexasHoldemPlayerStatisticsDataAccess statsDataAccess = uow.DataAccessManager.GetDataAccess<TexasHoldemPlayerStatistics>() as TexasHoldemPlayerStatisticsDataAccess;
				List<TexasHoldemPlayerStatistics> statSorted = statsDataAccess.ReadAll(); ;
				statSorted.Sort(MostHandsStats);
				for (int c = 0; c < 25; c++)
				{
					TexasHoldemPlayerStatistics stat = statSorted[c];
					pokerWatcherForm.AddStatistics(stat, true);
				}

				if (computeSegmentation)
				{
					TexasHoldemPlayerHandSummaryDataAccess handsDataAccess = uow.DataAccessManager.GetDataAccess<TexasHoldemPlayerHandSummary>() as TexasHoldemPlayerHandSummaryDataAccess;
					List<TexasHoldemPlayerHandSummary> allHands = handsDataAccess.Read("jonv11");
					allHands.Sort(FirstDateTimeHand);

					Dictionary<DateTime, List<TexasHoldemPlayerHandSummary>> HandsByDays = new Dictionary<DateTime, List<TexasHoldemPlayerHandSummary>>();
					Dictionary<DateTime, List<TexasHoldemPlayerHandSummary>> HandsByMonths = new Dictionary<DateTime, List<TexasHoldemPlayerHandSummary>>();
					Dictionary<long, List<TexasHoldemPlayerHandSummary>> HandsByWeeks = new Dictionary<long, List<TexasHoldemPlayerHandSummary>>();

					Dictionary<DateTime, double> HandsByDaysBalance = new Dictionary<DateTime, double>();
					Dictionary<DateTime, double> HandsByMonthsBalance = new Dictionary<DateTime, double>();
					Dictionary<long, double> HandsByWeeksBalance = new Dictionary<long, double>();

					GregorianCalendar cal = new GregorianCalendar(GregorianCalendarTypes.Localized);

					foreach (TexasHoldemPlayerHandSummary summary in allHands)
					{
						DateTime day = new DateTime(summary.HandSummary.HandDateTime.Year, summary.HandSummary.HandDateTime.Month, summary.HandSummary.HandDateTime.Day);
						DateTime month = new DateTime(summary.HandSummary.HandDateTime.Year, summary.HandSummary.HandDateTime.Month, 1);
						long week = (summary.HandSummary.HandDateTime.Year * 100) + cal.GetWeekOfYear(summary.HandSummary.HandDateTime, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
						List<TexasHoldemPlayerHandSummary> byDays;
						List<TexasHoldemPlayerHandSummary> byMonths;
						List<TexasHoldemPlayerHandSummary> byWeeks;
						if (!HandsByDays.TryGetValue(day, out byDays))
						{
							byDays = new List<TexasHoldemPlayerHandSummary>();
							HandsByDays.Add(day, byDays);
							HandsByDaysBalance.Add(day, 0);
						}
						if (!HandsByMonths.TryGetValue(month, out byMonths))
						{
							byMonths = new List<TexasHoldemPlayerHandSummary>();
							HandsByMonths.Add(month, byMonths);
							HandsByMonthsBalance.Add(month, 0);
						}
						if (!HandsByWeeks.TryGetValue(week, out byWeeks))
						{
							byWeeks = new List<TexasHoldemPlayerHandSummary>();
							HandsByWeeks.Add(week, byWeeks);
							HandsByWeeksBalance.Add(week, 0);
						}
						byDays.Add(summary);
						byMonths.Add(summary);
						byWeeks.Add(summary);
						if (summary.PlayerBalance != 0)
						{
							double ratio = (summary.HandSummary.Currency == "USD" ? Program.USDRatio : 1.0);
							HandsByWeeksBalance[week] += summary.PlayerBalance * ratio / 100.0;
							HandsByMonthsBalance[month] += summary.PlayerBalance * ratio / 100.0;
							HandsByDaysBalance[day] += summary.PlayerBalance * ratio / 100.0;
						}
					}

				}

				Application.Run(pokerWatcherForm);

			}
			else
			{
				PokerWatcherMainForm pokerWatcherMainForm = new PokerWatcherMainForm(configuration, uow);
				Application.Run(pokerWatcherMainForm);
			}

		}
		public static int FirstDateTimeHand(TexasHoldemPlayerHandSummary a, TexasHoldemPlayerHandSummary b)
		{
			int compare = a.HandSummary.HandDateTime.CompareTo(b.HandSummary.HandDateTime);
			return compare;
		}
		public static int LastChangesStats(TexasHoldemPlayerStatistics a, TexasHoldemPlayerStatistics b)
		{
			
			int compare = -a.LastChanges.CompareTo(b.LastChanges);
			if (compare == 0)
				return -a.HandCount.CompareTo(b.HandCount);
			else
			{
				TimeSpan duration;
				if(compare < 0)
					duration = a.LastChanges.Subtract(b.LastChanges);
				else
					duration = b.LastChanges.Subtract(a.LastChanges);
				if(duration.TotalMinutes < 10)
					return -a.HandCount.CompareTo(b.HandCount);
			}
			return compare;
		}
		public static int MostHandsStats(TexasHoldemPlayerStatistics a, TexasHoldemPlayerStatistics b)
		{
			return -a.HandCount.CompareTo(b.HandCount);
		}
	}
}
